#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
用户资料验证服务 - 提供资料完整度计算、字典验证和数据保护功能
"""

from typing import Dict, List, Optional, Any, Tuple
import json
import re
from datetime import datetime, date
from app.models.user import User
from app.models.user_profile import UserProfile
from app.services.dict_service import DictService


class ProfileValidationService:
    """用户资料验证服务类"""
    
    # 基础必填字段权重配置
    BASIC_REQUIRED_FIELDS = {
        'real_name': {'weight': 15, 'name': '真实姓名'},
        'gender': {'weight': 10, 'name': '性别'},
        'birthday': {'weight': 10, 'name': '生日'},
        'height': {'weight': 5, 'name': '身高'},
        'weight': {'weight': 5, 'name': '体重'},
        'city': {'weight': 10, 'name': '所在城市'},
    }
    
    # 详细资料字段权重配置
    PROFILE_FIELDS = {
        'education': {'weight': 8, 'name': '学历', 'dict_code': 'education'},
        'occupation': {'weight': 8, 'name': '职业', 'dict_code': 'occupation'},
        'income_range': {'weight': 8, 'name': '收入范围', 'dict_code': 'income_range'},
        'marital_status': {'weight': 6, 'name': '婚姻状况', 'dict_code': 'marital_status'},
        'housing_status': {'weight': 5, 'name': '住房情况', 'dict_code': 'housing_status'},
        'car_status': {'weight': 3, 'name': '购车情况', 'dict_code': 'car_status'},
        'smoking_habit': {'weight': 3, 'name': '吸烟习惯', 'dict_code': 'smoking_habit'},
        'drinking_habit': {'weight': 3, 'name': '饮酒习惯', 'dict_code': 'drinking_habit'},
        'hometown': {'weight': 4, 'name': '家乡'},
        'work_city': {'weight': 4, 'name': '工作城市'},
        'self_intro': {'weight': 5, 'name': '自我介绍'},
        'personality_traits': {'weight': 3, 'name': '性格特点', 'dict_code': 'personality_traits'},
        'hobby_tags': {'weight': 3, 'name': '兴趣爱好', 'dict_code': 'hobbies'},
    }
    
    # 敏感字段列表（需要脱敏处理）
    SENSITIVE_FIELDS = ['real_name', 'phone', 'wechat_number', 'address']
    
    @classmethod
    def calculate_completeness(cls, user_id: int) -> Dict[str, Any]:
        """
        计算用户资料完整度
        
        Args:
            user_id: 用户ID
            
        Returns:
            完整度信息字典
        """
        try:
            user = User.query.get(user_id)
            if not user:
                return {
                    'total_percentage': 0,
                    'basic_percentage': 0,
                    'profile_percentage': 0,
                    'missing_fields': [],
                    'error': '用户不存在'
                }
            
            profile = UserProfile.query.filter_by(user_id=user_id).first()
            
            # 计算基础信息完整度
            basic_score = 0
            basic_total = sum(field['weight'] for field in cls.BASIC_REQUIRED_FIELDS.values())
            basic_missing = []
            
            for field, config in cls.BASIC_REQUIRED_FIELDS.items():
                value = getattr(user, field, None)
                if cls._is_field_valid(value):
                    basic_score += config['weight']
                else:
                    basic_missing.append({
                        'field': field,
                        'name': config['name'],
                        'weight': config['weight']
                    })
            
            basic_percentage = (basic_score / basic_total * 100) if basic_total > 0 else 0
            
            # 计算详细资料完整度
            profile_score = 0
            profile_total = sum(field['weight'] for field in cls.PROFILE_FIELDS.values())
            profile_missing = []
            
            for field, config in cls.PROFILE_FIELDS.items():
                value = getattr(profile, field, None) if profile else None
                if cls._is_field_valid(value):
                    profile_score += config['weight']
                else:
                    profile_missing.append({
                        'field': field,
                        'name': config['name'],
                        'weight': config['weight']
                    })
            
            profile_percentage = (profile_score / profile_total * 100) if profile_total > 0 else 0
            
            # 计算总完整度（基础信息权重60%，详细资料权重40%）
            total_percentage = basic_percentage * 0.6 + profile_percentage * 0.4
            
            return {
                'total_percentage': round(total_percentage, 2),
                'basic_percentage': round(basic_percentage, 2),
                'profile_percentage': round(profile_percentage, 2),
                'basic_score': basic_score,
                'basic_total': basic_total,
                'profile_score': profile_score,
                'profile_total': profile_total,
                'missing_fields': {
                    'basic': basic_missing,
                    'profile': profile_missing
                },
                'total_missing_count': len(basic_missing) + len(profile_missing),
                'completeness_level': cls._get_completeness_level(total_percentage)
            }
            
        except Exception as e:
            return {
                'total_percentage': 0,
                'basic_percentage': 0,
                'profile_percentage': 0,
                'missing_fields': [],
                'error': f'计算完整度失败: {str(e)}'
            }
    
    @classmethod
    def validate_profile_data(cls, profile_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        验证用户资料数据
        
        Args:
            profile_data: 用户资料数据
            
        Returns:
            验证结果
        """
        validation_result = {
            'is_valid': True,
            'errors': [],
            'warnings': [],
            'dict_validations': {}
        }
        
        try:
            # 验证基础字段
            for field, value in profile_data.items():
                if field in cls.BASIC_REQUIRED_FIELDS:
                    validation = cls._validate_basic_field(field, value)
                    if not validation['is_valid']:
                        validation_result['errors'].extend(validation['errors'])
                        validation_result['is_valid'] = False
                
                elif field in cls.PROFILE_FIELDS:
                    field_config = cls.PROFILE_FIELDS[field]
                    
                    # 字典字段验证
                    if 'dict_code' in field_config:
                        dict_validation = cls._validate_dict_field(
                            field_config['dict_code'], value
                        )
                        validation_result['dict_validations'][field] = dict_validation
                        
                        if not dict_validation['is_valid']:
                            validation_result['errors'].append(
                                f"{field_config['name']}值无效: {dict_validation['error']}"
                            )
                            validation_result['is_valid'] = False
                    
                    # 特殊字段验证
                    elif field in ['self_intro']:
                        if value and len(str(value)) > 500:
                            validation_result['warnings'].append(
                                f"{field_config['name']}长度建议不超过500字符"
                            )
            
            return validation_result
            
        except Exception as e:
            return {
                'is_valid': False,
                'errors': [f'验证失败: {str(e)}'],
                'warnings': [],
                'dict_validations': {}
            }
    
    @classmethod
    def sanitize_profile_data(cls, user_data: Dict[str, Any], 
                            for_public: bool = True) -> Dict[str, Any]:
        """
        脱敏处理用户资料数据
        
        Args:
            user_data: 用户数据
            for_public: 是否为公开展示（True=脱敏，False=不脱敏）
            
        Returns:
            处理后的用户数据
        """
        if not for_public:
            return user_data
        
        sanitized_data = user_data.copy()
        
        try:
            # 脱敏处理敏感字段
            for field in cls.SENSITIVE_FIELDS:
                if field in sanitized_data:
                    value = sanitized_data[field]
                    if value:
                        sanitized_data[field] = cls._mask_sensitive_data(field, str(value))
            
            # 处理详细资料中的敏感信息
            if 'profile' in sanitized_data and sanitized_data['profile']:
                profile_data = sanitized_data['profile']
                
                # 脱敏公司名称（只显示首尾字符）
                if 'company' in profile_data and profile_data['company']:
                    company = str(profile_data['company'])
                    if len(company) > 2:
                        profile_data['company'] = company[0] + '*' * (len(company) - 2) + company[-1]
                
                # 脱敏学校名称
                if 'school' in profile_data and profile_data['school']:
                    school = str(profile_data['school'])
                    if len(school) > 4:
                        profile_data['school'] = school[:2] + '*' * (len(school) - 4) + school[-2:]
            
            return sanitized_data
            
        except Exception as e:
            # 如果脱敏失败，返回原数据但记录错误
            sanitized_data['_sanitization_error'] = str(e)
            return sanitized_data
    
    @classmethod
    def get_profile_suggestions(cls, user_id: int) -> List[Dict[str, Any]]:
        """
        获取资料完善建议
        
        Args:
            user_id: 用户ID
            
        Returns:
            建议列表
        """
        try:
            completeness_info = cls.calculate_completeness(user_id)
            suggestions = []
            
            # 根据缺失字段生成建议
            missing_fields = completeness_info.get('missing_fields', {})
            
            # 基础信息建议
            basic_missing = missing_fields.get('basic', [])
            if basic_missing:
                # 按权重排序，优先建议完善权重高的字段
                basic_missing.sort(key=lambda x: x['weight'], reverse=True)
                
                for field_info in basic_missing[:3]:  # 只显示前3个最重要的
                    suggestions.append({
                        'type': 'basic',
                        'priority': 'high' if field_info['weight'] >= 10 else 'medium',
                        'field': field_info['field'],
                        'message': f"完善{field_info['name']}信息，提升资料可信度",
                        'weight': field_info['weight']
                    })
            
            # 详细资料建议
            profile_missing = missing_fields.get('profile', [])
            if profile_missing:
                profile_missing.sort(key=lambda x: x['weight'], reverse=True)
                
                for field_info in profile_missing[:5]:  # 显示前5个
                    suggestions.append({
                        'type': 'profile',
                        'priority': 'high' if field_info['weight'] >= 6 else 'medium',
                        'field': field_info['field'],
                        'message': f"完善{field_info['name']}信息，提高匹配精度",
                        'weight': field_info['weight']
                    })
            
            # 添加通用建议
            total_percentage = completeness_info.get('total_percentage', 0)
            if total_percentage < 30:
                suggestions.insert(0, {
                    'type': 'general',
                    'priority': 'high',
                    'message': "资料完整度较低，建议尽快完善基本信息",
                    'action': 'complete_basic'
                })
            elif total_percentage < 60:
                suggestions.append({
                    'type': 'general',
                    'priority': 'medium',
                    'message': "资料完整度中等，继续完善可提高匹配成功率",
                    'action': 'complete_profile'
                })
            elif total_percentage < 80:
                suggestions.append({
                    'type': 'general',
                    'priority': 'low',
                    'message': "资料较为完整，可考虑添加更多兴趣爱好标签",
                    'action': 'add_hobbies'
                })
            
            return suggestions
            
        except Exception as e:
            return [{
                'type': 'error',
                'priority': 'high',
                'message': f'获取建议失败: {str(e)}'
            }]
    
    @classmethod
    def _is_field_valid(cls, value: Any) -> bool:
        """检查字段值是否有效"""
        if value is None:
            return False
        if isinstance(value, str) and not value.strip():
            return False
        if isinstance(value, (list, dict)) and not value:
            return False
        return True
    
    @classmethod
    def _validate_basic_field(cls, field: str, value: Any) -> Dict[str, Any]:
        """验证基础字段"""
        result = {'is_valid': True, 'errors': []}
        
        try:
            if field == 'gender' and value not in [1, 2]:
                result['is_valid'] = False
                result['errors'].append('性别值必须为1(男)或2(女)')
            
            elif field == 'birthday':
                if isinstance(value, str):
                    try:
                        birthday = datetime.strptime(value, '%Y-%m-%d').date()
                        # 检查年龄合理性（18-80岁）
                        today = date.today()
                        age = today.year - birthday.year - ((today.month, today.day) < (birthday.month, birthday.day))
                        if age < 18 or age > 80:
                            result['errors'].append('年龄必须在18-80岁之间')
                    except ValueError:
                        result['is_valid'] = False
                        result['errors'].append('生日格式必须为YYYY-MM-DD')
            
            elif field in ['height', 'weight']:
                if isinstance(value, (int, float)):
                    if field == 'height' and (value < 140 or value > 220):
                        result['errors'].append('身高必须在140-220cm之间')
                    elif field == 'weight' and (value < 40 or value > 200):
                        result['errors'].append('体重必须在40-200kg之间')
            
            elif field == 'real_name':
                if value and len(str(value)) < 2:
                    result['errors'].append('真实姓名至少2个字符')
            
            if result['errors']:
                result['is_valid'] = False
            
            return result
            
        except Exception as e:
            return {
                'is_valid': False,
                'errors': [f'字段验证失败: {str(e)}']
            }
    
    @classmethod
    def _validate_dict_field(cls, dict_code: str, value: Any) -> Dict[str, Any]:
        """验证字典字段"""
        if not value:
            return {'is_valid': True, 'error': None}
        
        try:
            # 处理JSON数组格式的值
            if isinstance(value, str) and value.startswith('['):
                values = DictService.parse_json_dict_values(value)
            elif isinstance(value, list):
                values = value
            else:
                values = [str(value)]
            
            # 验证每个值
            invalid_values = []
            for val in values:
                if not DictService.validate_dict_value(dict_code, str(val)):
                    invalid_values.append(val)
            
            if invalid_values:
                return {
                    'is_valid': False,
                    'error': f'无效的字典值: {", ".join(invalid_values)}'
                }
            
            return {'is_valid': True, 'error': None}
            
        except Exception as e:
            return {
                'is_valid': False,
                'error': f'字典验证失败: {str(e)}'
            }
    
    @classmethod
    def _mask_sensitive_data(cls, field: str, value: str) -> str:
        """脱敏敏感数据"""
        if field == 'real_name':
            if len(value) <= 1:
                return value
            elif len(value) == 2:
                return value[0] + '*'
            else:
                return value[0] + '*' * (len(value) - 2) + value[-1]
        
        elif field == 'phone':
            if len(value) == 11:
                return value[:3] + '****' + value[-4:]
            else:
                return value[:2] + '*' * (len(value) - 4) + value[-2:] if len(value) > 4 else value
        
        elif field == 'wechat_number':
            if len(value) > 4:
                return value[:2] + '*' * (len(value) - 4) + value[-2:]
            else:
                return '*' * len(value)
        
        elif field == 'address':
            if len(value) > 6:
                return value[:3] + '*' * (len(value) - 6) + value[-3:]
            else:
                return value[:1] + '*' * (len(value) - 1)
        
        return value
    
    @classmethod
    def _get_completeness_level(cls, percentage: float) -> str:
        """获取完整度等级"""
        if percentage >= 90:
            return '完美'
        elif percentage >= 80:
            return '优秀'
        elif percentage >= 60:
            return '良好'
        elif percentage >= 40:
            return '一般'
        elif percentage >= 20:
            return '较低'
        else:
            return '极低' 